package tech.lq0.dreamaticvoyage.recipe;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.minecraft.core.NonNullList;
import net.minecraft.core.RegistryAccess;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import net.minecraftforge.fluids.FluidStack;
import tech.lq0.dreamaticvoyage.Utils;
import tech.lq0.dreamaticvoyage.tools.RecipeTool;

import javax.annotation.Nullable;

public class FukamizuFermentingRecipe implements Recipe<SimpleFluidContainer> {

    private final Ingredient input;
    private final Ingredient yeast;
    private final FluidStack fluid;
    private final FluidStack output;
    private final ResourceLocation id;

    public FukamizuFermentingRecipe(Ingredient input, Ingredient yeast, FluidStack fluid, FluidStack output, ResourceLocation id) {
        this.input = input;
        this.yeast = yeast;
        this.fluid = fluid;
        this.output = output;
        this.id = id;
    }

    public FluidStack getOutput() {
        return output.copy();
    }

    public FluidStack getInput() {
        return fluid.copy();
    }

    @Override
    public boolean matches(SimpleFluidContainer pContainer, Level pLevel) {
        if (pLevel.isClientSide() || pContainer.getContainerSize() < 2 || pContainer.getFluidSize() < 1) {
            return false;
        }

        return input.test(pContainer.getItem(0)) && yeast.test(pContainer.getItem(1))
                && pContainer.getFluid(0).containsFluid(fluid.copy());
    }

    @Override
    public ItemStack assemble(SimpleFluidContainer pContainer, RegistryAccess pRegistryAccess) {
        return ItemStack.EMPTY;
    }

    @Override
    public NonNullList<Ingredient> getIngredients() {
        return NonNullList.of(input, input, yeast);
    }

    @Override
    public boolean canCraftInDimensions(int pWidth, int pHeight) {
        return true;
    }

    @Override
    public ItemStack getResultItem(RegistryAccess pRegistryAccess) {
        return ItemStack.EMPTY;
    }

    @Override
    public boolean isSpecial() {
        return true;
    }

    @Override
    public ResourceLocation getId() {
        return this.id;
    }

    @Override
    public RecipeSerializer<?> getSerializer() {
        return Serializer.INSTANCE;
    }

    @Override
    public RecipeType<?> getType() {
        return Type.INSTANCE;
    }

    public static class Type implements RecipeType<FukamizuFermentingRecipe> {
        public static final FukamizuFermentingRecipe.Type INSTANCE = new FukamizuFermentingRecipe.Type();
        public static final String ID = "fukamizu_fermenting";
    }

    public static class Serializer implements RecipeSerializer<FukamizuFermentingRecipe> {
        public static final FukamizuFermentingRecipe.Serializer INSTANCE = new FukamizuFermentingRecipe.Serializer();
        public static final ResourceLocation ID = Utils.loc("fukamizu_fermenting");

        @Override
        public FukamizuFermentingRecipe fromJson(ResourceLocation pRecipeId, JsonObject pSerializedRecipe) {
            JsonElement inputIngredient = GsonHelper.isArrayNode(pSerializedRecipe, "input") ?
                    GsonHelper.getAsJsonArray(pSerializedRecipe, "input") : GsonHelper.getAsJsonObject(pSerializedRecipe, "input");
            var input = Ingredient.fromJson(inputIngredient);
            var yeast = RecipeTool.getIngredientFromJson(pSerializedRecipe, "yeast");

            FluidStack fluid = RecipeTool.getFluidFromJson(pSerializedRecipe, "fluid");
            FluidStack output = RecipeTool.getFluidFromJson(pSerializedRecipe, "output");

            return new FukamizuFermentingRecipe(input, yeast, fluid, output, pRecipeId);
        }

        @Override
        public @Nullable FukamizuFermentingRecipe fromNetwork(ResourceLocation pRecipeId, FriendlyByteBuf pBuffer) {
            Ingredient input = Ingredient.fromNetwork(pBuffer);
            Ingredient yeast = Ingredient.fromNetwork(pBuffer);
            FluidStack fluid = FluidStack.readFromPacket(pBuffer);
            FluidStack output = FluidStack.readFromPacket(pBuffer);

            return new FukamizuFermentingRecipe(input, yeast, fluid, output, pRecipeId);
        }

        @Override
        public void toNetwork(FriendlyByteBuf pBuffer, FukamizuFermentingRecipe pRecipe) {
            pRecipe.input.toNetwork(pBuffer);
            pRecipe.yeast.toNetwork(pBuffer);
            pRecipe.fluid.writeToPacket(pBuffer);
            pRecipe.output.writeToPacket(pBuffer);
        }
    }
}
